﻿using System.Collections.Generic;
using System.Linq;
using Fee.Orders;
using Fee.Searchers;
using Fee.ViewModel;
using Microsoft.EntityFrameworkCore;

namespace Fee.Stores.Ef
{
    public class ConstructionTaskStore<T> : IConstructionTaskStore<T> where T : FeeDbContext
    {
        private readonly T _context;

        public ConstructionTaskStore(T context)
        {
            _context = context;
        }

        public ConstructionTask GetByStation(int stationId)
        {
            var re = _context.ConstructionTasks.Include(f => f.Station)
                .Include(f => f.Details).ThenInclude(f => f.Contract).ThenInclude(f => f.Vendor)
                .Include(f => f.Details).ThenInclude(f => f.Contract)
                .Include(f => f.Details).ThenInclude(f => f.Project)
                .Include(f => f.CostDetails).ThenInclude(f => f.ProcessInfo)
                .Include(f => f.PlanCosts).ThenInclude(f => f.ProcessInfo)
                .FirstOrDefault(f => f.Station.Id == stationId);
            if (re != null)
                _context.Entry(re).Reference(f => f.Station).TargetEntry.Reference(f => f.District).EntityEntry
                    .Reference(f => f.OrderDistrict).Load();

            return re;
        }

        public IEnumerable<StationDetailViewModel> List(ConstructionTaskSearcher pager, out int total)
        {
            var quStation = from station in _context.Stations.Include(f => f.District).Include(f => f.OrderDistrict)
                            join task in _context.ConstructionTasks on station equals task.Station into fa
                            from taskSub in fa.DefaultIfEmpty()
                            where
                                (!pager.HasTask || taskSub != null) &&
                                (string.IsNullOrEmpty(pager.StationName) || station.Code == pager.StationName)
                                && (pager.StationType == null || station.Type == pager.StationType.Value)
                                && (pager.DistrictId == 0 || station.District.Id == pager.DistrictId)
                                && (pager.StationStatus == null || station.Status == pager.StationStatus.Value)
                            select new StationDetailViewModel(station, taskSub);


            total = quStation.Count();
            return quStation.Skip(pager.GetSkip()).Take(pager.GetTake()).ToList();
        }

        public ConstructionTask Get(int id)
        {
            return _context.ConstructionTasks
                .Include(f => f.Station).ThenInclude(f => f.District)
                .Include(f => f.Station).ThenInclude(f => f.OrderDistrict)
                .Include(f => f.Details).ThenInclude(f => f.ProcessInfo)
                .Include(f => f.Details).ThenInclude(f => f.Project)
                .Include(f => f.Details).ThenInclude(f => f.Contract).ThenInclude(f => f.Vendor)
                .Include(f => f.Details).ThenInclude(f => f.Contract)
                .Include(f => f.PlanCosts).ThenInclude(f => f.ProcessInfo)
                .Include(f => f.CostDetails).ThenInclude(f => f.ProcessInfo)
                .FirstOrDefault(f => f.Id == id);
        }

        public IEnumerable<BudgetViewModel> BudgetSearches(StationBudgetSearch searcher, out int total)
        {
            var project = _context.Set<ConstructionDetail>()
                .FirstOrDefault(f => f.Project.No == searcher.ProjectNumber);

            var details = from cost in _context.Set<ConstructionTaskPlanCost>()
                          join task in _context.Set<ConstructionTask>()
                                  .Include(_ => _.Station).ThenInclude(f => f.District)
                                  .Include(_ => _.Station).ThenInclude(f => f.OrderDistrict)
                                  .Include(f => f.PlanCosts)
                                  .Include(f => f.Details).ThenInclude(f => f.Contract).ThenInclude(f => f.Vendor)
                                  .Include(f => f.Details).ThenInclude(f => f.Project)
                              on cost.TaskId equals task.Id
                          where
                              (string.IsNullOrEmpty(searcher.Station.Name) || task.Station.Name.Contains(searcher.Station.Name))
                              &&
                              (string.IsNullOrEmpty(searcher.Station.Code) || task.Station.Code == searcher.Station.Code)
                              && (cost.ConstructionEffect || cost.DesignEffect || cost.SupervisorEffect)
                              && (project == null || task.Details.Contains(project))
                          select new BudgetViewModel(task, cost);
            total = details.Count();
            return details.Skip(searcher.GetSkip()).Take(searcher.GetTake()).ToList();
        }
    }
}